﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Threading;
using ExitGames.Client.Photon;
using MetroFramework;
using MetroFramework.Forms;
using PhotonServerCommon.Enums;
using PhotonServerCommon.Messages;
using PhotonServerCommon.Messages.Helper;
using PhotonTestClient.Forms.Account;
using PhotonTestClient.Helper;
using PhotonTestClient.Photon;

namespace PhotonTestClient
{
    public partial class PhotonTestClient : MetroForm
    {
        private PhotonPeer Peer { get; }
        public bool PeerConnecting { private get; set; }
        public bool PeerConnected { private get; set; }
        private DispatcherTimer DispatcherTimer { get; }
        private string LoginName { get; set; }
        private string LoginPass { get; set; }

        public PhotonTestClient()
        {
            InitializeComponent();

            StyleManager = mmStyleManager;
            StyleManager.Theme = MetroThemeStyle.Dark;
            StyleManager.Style = MetroColorStyle.Orange;
            
            PhotonListener listener = new PhotonListener {MasterWindow = this};

            Peer = new PhotonPeer(listener, ConnectionProtocol.Udp) {DebugOut = DebugLevel.WARNING};
            PeerConnecting = false;
            PeerConnected = false;

            if (Peer == null)
            {
                SetStatusText(LogHelper.GetTimeStamp(), "PhotonClientPeer could not be created!");
            }

            DispatcherTimer = new DispatcherTimer();
            DispatcherTimer.Tick += dispatcherTimer_tick;
            DispatcherTimer.Interval = TimeSpan.FromMilliseconds(1);

            SetStatusText(LogHelper.GetTimeStamp(), Peer.PeerState.ToString());

            statusStrip1.BackColor = Color.Red;
        }

        private void dispatcherTimer_tick(object sender, EventArgs e)
        {
            Service();
            if (PeerConnected)
            {
                statusStrip1.BackColor = Color.DarkGreen;
            }
            else if (PeerConnecting && !PeerConnected)
            {
                statusStrip1.BackColor = Color.Orange;
            }
            else
            {
                statusStrip1.BackColor = Color.DarkRed;
            }
        }

        private void Service()
        {
            Peer.Service();
        }

        public void SetStatusText(string timeStamp, string text)
        {
            if (statusTextBox.InvokeRequired)
            {
                SetTextThreadSafe d = SetStatusText;
                Invoke(d, timeStamp, text);
            }
            else
            {
                statusTextBox.AppendText(timeStamp + ": " + text + "\n");
            }
        }

        private delegate void SetTextThreadSafe(string timeStamp, string text);
        
        private void PhotonTestClient_Load(object sender, EventArgs e)
        {

        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }
        
        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetStatusText(LogHelper.GetTimeStamp(), "Trying to connect to " + ClientSettings.Default.MasterServerAddress + ":" + ClientSettings.Default.MasterServerClientUdp + " - " + ClientSettings.Default.MasterApplication);
            if (Peer.Connect(
                    ClientSettings.Default.MasterServerAddress + ":" + ClientSettings.Default.MasterServerClientUdp,
                    ClientSettings.Default.MasterApplication))
            {
                PeerConnecting = true;
                DispatcherTimer.Start();
                SetStatusText(LogHelper.GetTimeStamp(), Peer.PeerState.ToString());
            }
            else
            {
                SetStatusText(LogHelper.GetTimeStamp(), "Connection refused!");
            }
        }

        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Peer.Disconnect();
            statusStrip1.BackColor = Color.DarkRed;
        }

        private void registerAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RegisterAccount form = new RegisterAccount
            {
                OwnerMetroForm = this,
                StyleManager = StyleManager
            };
            StyleManager.Clone(form);
            form.ShowDialog();
            form.Dispose();
        }

        public void RegisterAccount(string foreName, string lastName, string loginName, string passWord)
        {
            AccountRegisterMessage message = new AccountRegisterMessage()
                                             {
                                                 GivenName = foreName,
                                                 SureName = lastName,
                                                 LoginName = loginName,
                                                 LoginPassword = passWord
                                             };

            Dictionary<byte, object> parameters = new Dictionary<byte, object>
                                                  {
                                                      {
                                                          (byte) ParameterCodes.OperationSubCode,
                                                          OperationSubCodes.RegisterAccount
                                                      },
                                                      {
                                                          (byte) ParameterCodes.AccountRegisterMessage,
                                                          MessageSerializer.SerializeMessage(message)
                                                      }
                                                  };

            OperationRequest operation = new OperationRequest()
            {
                OperationCode = (byte)OperationCodes.Account,
                Parameters = parameters
            };

            SetStatusText(LogHelper.GetTimeStamp(),
                $"Sending request to server (Code = {operation.OperationCode} - SubCode = {parameters[(byte) ParameterCodes.OperationSubCode]} - Message = {message.GetType().Name}");

            Peer.OpCustom(operation, true, 0, false);
        }

        private void loginAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoginAccount form = new LoginAccount
            {
                OwnerMetroForm = this,
                StyleManager = StyleManager
            };
            StyleManager.Clone(form);
            form.ShowDialog();
            form.Dispose();
        }

        public void LoginAccount(string loginName, string loginPass)
        {
            AccountLoginMessage message = new AccountLoginMessage() {LoginName = loginName, LoginPassword = loginPass};

            Dictionary<byte, object> parameters = new Dictionary<byte, object>
                                                  {
                                                      {
                                                          (byte) ParameterCodes.OperationSubCode,
                                                          OperationSubCodes.LoginAccount
                                                      },
                                                      {
                                                          (byte) ParameterCodes.AccountLoginMessage,
                                                          MessageSerializer.SerializeMessage(message)
                                                      }
                                                  };

            OperationRequest operation = new OperationRequest()
            {
                OperationCode = (byte)OperationCodes.Account,
                Parameters = parameters
            };
            SetStatusText(LogHelper.GetTimeStamp(),
                $"Sending request to server (Code = {operation.OperationCode} - SubCode = {parameters[(byte)ParameterCodes.OperationSubCode]} - Message = {message.GetType().Name}");
            Peer.OpCustom(operation, true, 0, false);

            LoginName = loginName;
            LoginPass = loginPass;
        }

        private void logoutAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AccountLogoutMessage message = new AccountLogoutMessage() {LoginName = LoginName, LoginPassword = LoginPass};

            Dictionary<byte, object> parameters = new Dictionary<byte, object>
                                                  {
                                                      {
                                                          (byte) ParameterCodes.OperationSubCode,
                                                          OperationSubCodes.LogoutAccount
                                                      },
                                                      {
                                                          (byte) ParameterCodes.AccountLogoutMessage,
                                                          MessageSerializer.SerializeMessage(message)
                                                      }
                                                  };

            OperationRequest operation = new OperationRequest()
            {
                OperationCode = (byte)OperationCodes.Account,
                Parameters = parameters
            };
            SetStatusText(LogHelper.GetTimeStamp(),
                $"Sending request to server (Code = {operation.OperationCode} - SubCode = {parameters[(byte)ParameterCodes.OperationSubCode]} - Message = {message.GetType().Name}");
            Peer.OpCustom(operation, true, 0, false);

        }

        private void deleteAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AccountDeleteMessage message = new AccountDeleteMessage { LoginName = LoginName, LoginPassword = LoginPass };

            Dictionary<byte, object> parameters = new Dictionary<byte, object>
                                                  {
                                                      {
                                                          (byte) ParameterCodes.OperationSubCode,
                                                          OperationSubCodes.DeleteAccount
                                                      },
                                                      {
                                                          (byte) ParameterCodes.AccountDeleteMessage,
                                                          MessageSerializer.SerializeMessage(message)
                                                      }
                                                  };

            OperationRequest operation = new OperationRequest()
            {
                OperationCode = (byte)OperationCodes.Account,
                Parameters = parameters
            };
            SetStatusText(LogHelper.GetTimeStamp(),
                $"Sending request to server (Code = {operation.OperationCode} - SubCode = {parameters[(byte)ParameterCodes.OperationSubCode]} - Message = {message.GetType().Name}");
            Peer.OpCustom(operation, true, 0, false);
        }

        private void getRealmListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OperationRequest operation = new OperationRequest
            {
                OperationCode = (byte)OperationCodes.Transfer,
                Parameters =
                                                 new Dictionary<byte, object>()
                                                 {
                                                     {
                                                         (byte)
                                                         ParameterCodes
                                                         .OperationSubCode,
                                                         OperationSubCodes
                                                         .RequestRealmList
                                                     },
                                                     {(byte) ParameterCodes.RealmRegion, "DE"}
                                                 }
            };
            SetStatusText(LogHelper.GetTimeStamp(),
                $"Sending request to server (Code = {operation.OperationCode} - SubCode = {OperationSubCodes.RequestRealmList} - Message = None");
            Peer.OpCustom(operation, true, 0, false);
        }
    }
}
